﻿namespace Gateway.Common.Extensions
{
    public static class DateTimeExtensions
    {
        /// <summary>
        /// 自定义时间格式，默认返回返回格式：2019-01-21 20:57:51
        /// </summary>
        /// <param name="time"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static string ToStandardString(this DateTime time, string format)
        {
            return string.IsNullOrWhiteSpace(format) ? time.ToStandardString() : time.ToString(format);
        }

        public static string ToStandardString(this DateTime time)
        {
            return time.ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        /// 自定义时间格式，默认返回返回格式：05-09
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ToMonthDayString(this DateTime time)
        {
            return time.ToString("MM-dd");
        }

        /// <summary>
        /// 返回返回格式：2019-01-21 20:57
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ToStringStandardExcludingSeconds(this DateTime time)
        {
            return time.ToString("yyyy-MM-dd HH:mm");
        }

        /// <summary>
        /// 返回当前时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ToTimestamp(this DateTime time)
        {
            return (time.ToUniversalTime().Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks) / 10000000;
        }
        
        /// <summary>
        /// 时间戳转byte数组
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static byte[] ToHexByte(this long timestamp)
        {
            string str = timestamp.ToString("X4");
            str = str.Replace(":", "");
            if (str.Length % 2 != 0)
                str += " ";
            byte[] bytes = new byte[str.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
            }

            return bytes;
        }
        /// <summary>
        /// 时间戳转时间
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this long timestamp)
        {
            return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddMilliseconds(timestamp).AddHours(8);
        }

        /// <summary>  
        /// 时间戳Timestamp转换成日期  
        /// </summary>  
        /// <param name="timeStamp"></param>  
        /// <returns></returns>  
        public static DateTime ToDateTime(this int timeStamp)
        {
            var dtStart = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), TimeZoneInfo.Local);
            var lTime = (long)timeStamp * 10000000;
            var toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }

        /// <summary>
        /// 获取时间差 格式为"x时x分x秒"
        /// </summary>
        /// <param name="dt1"></param>
        /// <param name="dt2"></param>
        /// <returns></returns>
        public static string ToTimeDiffString(this DateTime dt1, DateTime dt2)
        {
            var timeSpan = dt1.Subtract(dt2).Duration();
            var hours = timeSpan.Days * 24 + timeSpan.Hours;
            var minutes = timeSpan.Minutes;
            var seconds = timeSpan.Seconds;

            var result = string.Empty;
            if (hours > 0)
                result += $"{hours}时";
            if (minutes > 0 || (hours > 0 && seconds > 0))
                result += $"{minutes}分";
            if (seconds > 0)
                result += $"{seconds}秒";

            return result;
        }

        /// <summary>
        /// 获取前台显示时间特定格式 昨天和今天显示 "昨天 13:14" "12-12 01:12"
        /// </summary>
        /// <param name="time"></param>
        /// <param name="showtime"></param>
        /// <returns></returns>
        public static string ToShowTime(this DateTime time)
        {
            string result = string.Empty;
            DateTime yesterdayMinTime = DateTime.Now.AddDays(-1).Date;
            DateTime yesterdayMaxTime = DateTime.Now.Date.AddSeconds(-1);
            if (time >= DateTime.Now.Date && time <= DateTime.Now.Date.AddDays(1).AddSeconds(-1))
                result = "今天 " + time.ToString("HH:mm");
            else if (time >= yesterdayMinTime && time <= yesterdayMaxTime)
                result = "昨天 " + time.ToString("HH:mm");
            else
                result = time.ToString("MM-dd HH:mm");
            return result;
        }

        /// <summary>
        /// 取指定的日期是在那一年里的第几周
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static int GetWeekOfYear(this DateTime dt)
        {
            var tmpDate = DateTime.Parse(dt.ToString("yyyy-01-01"));
            return (dt.DayOfYear + 6 + (int)tmpDate.DayOfWeek) / 7;
        }

        /// <summary>
        /// 上周一
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetLastMonday(this DateTime dt)
        {
            return dt.Date.AddDays(1 - Convert.ToInt32(Convert.ToInt32(dt.DayOfWeek)) - 7);
        }

        /// <summary>
        /// 上周日
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static DateTime GetLastSunday(this DateTime dt)
        {
            return dt.Date.AddDays(Convert.ToInt32(-Convert.ToInt32(dt.DayOfWeek)));
        }

        /// <summary>
        /// 获取前周一和周日时间
        /// </summary>
        /// <returns></returns>
        public static Tuple<DateTime, DateTime> GetTwoWeekAgoDate()
        {
            var date = DateTime.Now;
            var m = (date.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : date.DayOfWeek) - DayOfWeek.Monday;
            var s = (date.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : date.DayOfWeek) - (DayOfWeek)7;
            return new Tuple<DateTime, DateTime>(date.AddDays((-14 - m)).Date, date.AddDays((-14 - s)).Date);
        }
        
        
        
        /// <summary>
        /// 将string转换为DateTime，若失败则返回日期最小值
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DateTime ParseToDateTime(this string str)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(str))
                {
                    return DateTime.MinValue;
                }
                if (str.Contains('-') || str.Contains('/'))
                {
                    return DateTime.Parse(str);
                }
                else
                {
                    int length = str.Length;
                    switch (length)
                    {
                        case 4:
                            return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture);

                        case 6:
                            return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture);

                        case 8:
                            return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture);

                        case 10:
                            return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture);

                        case 12:
                            return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture);

                        case 14:
                            return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);

                        default:
                            return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
                    }
                }
            }
            catch
            {
                return DateTime.MinValue;
            }
        }
    }
}